﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.ComponentModel.Composition;
using Moq;
using System.ComponentModel.Composition.Hosting;
using Steve.UI.Extensions;
using System.Web.Mvc;
using System.Web;
using Steve.UI;
using System.Web.Security;
using Microsoft.ComponentModel.Composition.Extensions.Web;
using Steve.UI.Administration;

namespace Steve.TestHelper
{
    //HACK: this is kind of a mess with all the web / mvc dependencies...

    public static class ComposablePartTestsExtensions
    {
        public static T ComposeController<T>(this ComposablePartTests tests) where T : class, IController, new()
        {
            return tests.Compose<T>();
        }
    }

    public abstract class ComposablePartTests
    {
        protected CompositionContainer Container { get; set; }
        protected ScopedContainerManager ScopedContainer { get; set; }
                
        static protected HttpContextBase HttpContextExport { get; private set; }
        static protected Mock<IAccountService> AccountMock { get; set; }

        class Exports
        {
            [Export]
            public ILoggingService Log
            {
                get
                {
                    return new Mock<ILoggingService>(MockBehavior.Loose).Object;
                }
            }

            [Export]
            public IAccountService Account
            {
                get
                {
                    return AccountMock.Object;
                }
            }

            [Export]
            public IHttpContextBaseBuilder HttpContextBuilder
            {
                get
                {
                    var mock = new Mock<IHttpContextBaseBuilder>();
                    mock.Setup(b => b.BuildCurrent()).Returns(HttpContextExport);
                    return mock.Object;
                }
            }
        }

        public virtual List<Type> GetTypesForCatalog()
        {
            return new List<Type>()
            {
                typeof(Exports),
                typeof(DefaultConfiguration), 
                typeof(PerRequestCacheService), 
                typeof(StubContentRepository),
                typeof(StubContentTypeRepository),
                typeof(StubCategoryRepository),
                typeof(StubSiteExplorerRepository),
                typeof(StubMetaRepository),
                typeof(StubContentAdministrationRepository)
            };
        }

        [TestInitialize]
        public void TestInitialize()
        {
            var catalog = new TypeCatalog(GetTypesForCatalog());
            HttpContextExport = MockWebHelpers.MockHttpContext();
            Container = new CompositionContainer(catalog);
            AccountMock = new Mock<IAccountService>(MockBehavior.Strict);

            ScopedContainer = new ScopedContainerManager(catalog);
            ScopedContainer.CreateRequestContainer(HttpContextExport.Items);

            SteveAdministrationSite.Initialize(ScopedContainer);

            StubSiteExplorerRepository.Clear();
            StubCategoryRepository.Clear();

            InitializeGlobalTestData();
        }

        protected virtual void InitializeGlobalTestData()
        {
        }

        public virtual T Compose<T>() where T : new()
        {
            return ScopedContainer.Compose<T>();
        }

        public virtual void Compose<T>(T obj)
        {
            ScopedContainer.Compose<T>(obj);
        }
    }
}
